﻿/*
  Copyright (c) 2011, Mikheev Rostislav
  Copyright (c) 2011, FreshFarsh team

  Steel Engine source code is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
/**
  @author Mikheev Rostislav <hacenator@gmail.com>
  @date 13.03.2011
  @brief Extended mathematic functions source
*/

#include "math_ext.h"

namespace _STEEL_NAMESPACE {

inline int NextPowerOfTwo(int a) {
  int val=1;

  while(val < a)
    val <<= 1;

  return val;
}

Point2f Bernstein(float u, Point2f *p) {
	Point2f a, b, c, d, r;

  Point2Scale(p[0], pow(u, 3), a);
  Point2Scale(p[1], 3 * pow(u, 2) * (1 - u), b);
  Point2Scale(p[2], 3 * u * pow((1 - u), 2), c);
  Point2Scale(p[3], pow((1 - u), 3), d);

  Point2Add(a, b, a);
  Point2Add(c, d, c);
	Point2Add(a, c, r);

  return r;
}

bool CollisionCircleWithCircle(const Point2f p1, const float radius1, const Point2f p2, const float radius2) {
  //TODO(hacenator) radius really must be >= 1?

  if (radius1 >= 1 && radius2 >= 1) {
    return (Point2Distance(p1, p2) <= (radius1 + radius2));
  } else {
    return false;
  }
}

bool SegmentsIntersection(const Point2f a1, const Point2f a2, 
	const Point2f b1, const Point2f b2, Point2f c) {
	
	float d = (a1.x - a2.x) * (b2.y - b1.y) - (a1.y - a2.y) * (b2.x - b1.x);
	float da = (a1.x - b1.x) * (b2.y - b1.y) - (a1.y - b1.y) * (b2.x - b1.x);
  float db = (a1.x - a2.x) * (a1.y - b1.y) - (a1.y - a2.y) * (a1.x - b1.x);

  if (fabs(d) < 0.000001f) {
    return false;
  } else {
    float ta = da / d;
    float tb = db / d;
    
    if ((0 <= ta) && (ta <= 1) && (0 <= tb) && (tb <= 1)) {
      c.x = a1.x + ta * (a2.x - a1.x);
      c.y = a1.y + ta * (a2.y - a1.y);
      return true;
    }
  }
  
  return false;
}

}
